#include "Wrapper.h"



_NS_OOP_BEGIN



template< class T >
Ptr< T >::Ptr ()
{

}



template< class T >
Ptr< T >::Ptr (const Ptr< T >& r_right) :
ObjectRef (r_right)
{
}



template< class T >
Ptr< T >::Ptr (Ptr< T >&& rr_right) :
ObjectRef (std::move (rr_right))
{

}



template< class T >
template< class T2 >
Ptr< T >::Ptr (const Ptr< T2 >& r_right) :
ObjectRef (r_right)
{
	// Check convertion by compiler
	T2* tmp1 = NULL;
	T* tmp2 = tmp1;
}



template< class T >
Ptr< T >::~Ptr ()
{
	if (__getRef () <= 1)
		_releaseNonObjectData ();
}



template< class T >
Ptr< T >&
Ptr< T >::operator= (const Ptr< T >& r_right)
{
	ObjectRef::operator= (r_right);

	return *this;
}



template< class T >
Ptr< T >& Ptr< T >::operator= (Ptr< T >&& rr_right)
{
	ObjectRef::operator= (std::move (rr_right));

	return *this;
}



template< class T >
template< class T2 >
Ptr< T >&
Ptr< T >::operator= (const Ptr< T2 >& r_right)
{
	ObjectRef::operator= (r_right);

	// Check convertion by compiler
	T2* tmp1 = NULL;
	T* tmp2 = tmp1;

	return *this;
}



template< class T >
T*
Ptr< T >::operator-> () throw (NullPtrException)
{
	if (__p_obj == NULL)
		OOPTHROW (NullPtrException ());
	return _getPtrToRealObject ();
}
template< class T >
const T*
Ptr< T >::operator-> () const throw (NullPtrException)
{
	if (__p_obj == NULL)
		OOPTHROW (NullPtrException ());
	return _getPtrToRealObject ();
}



template< class T >
T&
Ptr< T >::operator* () throw (NullPtrException)
{
	if (__p_obj == NULL)
		OOPTHROW (NullPtrException ());
	return *_getPtrToRealObject ();
}
template< class T >
const T&
Ptr< T >::operator* () const throw (NullPtrException)
{
	if (__p_obj == NULL)
		OOPTHROW (NullPtrException ());
	return *_getPtrToRealObject ();
}



template< class T >
T*
Ptr< T >::getExternRef ()
{
	__incrRef ();
	return _getPtrToRealObject ();
}
template< class T >
const T*
Ptr< T >::getExternRef () const
{
	__incrRef ();
	return _getPtrToRealObject ();
}



template< class T >
void
Ptr< T >::releaseExternRef ()
{
	__decrRef ();
}



template< class T >
Ptr< T >::Ptr (Object* p_obj) :
ObjectRef (p_obj)
{

}



template< class T >
T*
Ptr< T >::_getPtrToRealObject () const
{
	if (!__p_obj)
		return NULL;
	if (dynamic_cast< Wrapper* > (__p_obj))
		return (T*) ((Wrapper*)__p_obj)->getDataPtr ();
	return (T*) __p_obj;
}



template< class T >
void
Ptr< T >::__release ()
{
	_releaseNonObjectData ();
	ObjectRef::__release ();
}



template< class T >
void
Ptr< T >::_releaseNonObjectData ()
{
	if (dynamic_cast<Wrapper*> (__p_obj))
		delete _getPtrToRealObject ();
}



_NS_OOP_END